package com.xms.sdk.api.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xms.core.data.Entity;
import com.xms.core.model.KeyValuePair;
import com.xms.file.service.IAttachmentCreaterService;
import com.xms.schema.entity.Attribute;
import com.xms.schema.entity.RelationShip;
import com.xms.schema.extension.AttributeExt;
import com.xms.schema.service.attribute.IAttributeFinderService;
import com.xms.schema.service.entity.IEntityFinderService;
import com.xms.schema.service.relationship.IRelationShipFinderService;
import com.xms.sdk.api.model.SaveDataModel;
import com.xms.sdk.client.aggroot.*;
import com.xms.sdk.core.EntityReference;
import com.xms.sdk.extensions.EntityWrapper;
import com.xms.sdk.service.IDataCreater;
import com.xms.sdk.service.IDataUpdater;
import com.xms.utils.CollectionUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import com.xms.web.framework.controller.ApiBaseController;
import com.xms.web.framework.model.JsonResultObject;
import io.swagger.annotations.ApiOperation;
import org.apache.tomcat.util.http.fileupload.FileUploadBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Part;
import java.util.*;

/**
 * <p>
 * AggRootSaveController
 * </p>
 *
 * @author migo
 * @since 2021/9/14
 */
@RestController
@RequestMapping("{org}/api/data/aggrootsave")
public class AggRootSaveController extends ApiBaseController {
    private IEntityFinderService _entityFinderService;
    private IAttributeFinderService _attributeFinderService;
    private IRelationShipFinderService _relationShipFinderService;
    private IDataCreater _dataCreater;
    private IDataUpdater _dataUpdater;
    private IAggCreater _aggCreater;
    private IAggUpdater _aggUpdater;
    private IAggFinder _aggFinder;
    private IAttachmentCreaterService _attachmentCreaterService;

    @Autowired
    public AggRootSaveController(IEntityFinderService entityFinderService
            , IAttributeFinderService attributeFinderService
            , IRelationShipFinderService relationShipFinderService
            , IDataCreater dataCreater
            , IDataUpdater dataUpdater
            , IAggCreater aggCreater
            , IAggUpdater aggUpdater
            , IAggFinder aggFinder
            , IAttachmentCreaterService attachmentCreaterService) {
        _entityFinderService = entityFinderService;
        _attributeFinderService = attributeFinderService;
        _relationShipFinderService = relationShipFinderService;
        _dataCreater = dataCreater;
        _dataUpdater = dataUpdater;
        _aggCreater = aggCreater;
        _aggUpdater = aggUpdater;
        _aggFinder = aggFinder;
        _attachmentCreaterService = attachmentCreaterService;
    }

    @ApiOperation("保存记录")
    @PostMapping(value = "", consumes = FileUploadBase.MULTIPART_FORM_DATA)
    public JsonResultObject save(@RequestParam(value = "recordid", required = false) UUID recordid,
                                 @RequestParam(value = "entityid", required = true) UUID entityid,
                                 @RequestParam(value = "formid", required = false) UUID formid,
                                 @RequestParam(value = "relationshipname", required = false) String relationshipname,
                                 @RequestParam(value = "referencedrecordid", required = false) UUID referencedrecordid,
                                 @RequestParam(value = "data", required = false) String data,
                                 @RequestParam(value = "child", required = false) String child) {
        //@RequestParam SaveDataModel model
        if (UUIDUtil.isEmpty(entityid)) {
            return JNotFound();
        }
        com.xms.schema.entity.Entity entityMetaData = _entityFinderService.getById(entityid);
        if (entityMetaData == null) {
            return JNotFound();
        }
        SaveDataModel model = new SaveDataModel();
        model.EntityId = entityid;
        model.RecordId = recordid;
        model.FormId = formid;
        model.RelationShipName = relationshipname;
        model.ReferencedRecordId = referencedrecordid;
        model.Data = data;
        model.Child = child;

        AggregateRoot aggregateRoot = new AggregateRoot();
        List<Attribute> attributeMetaDatas = _attributeFinderService.getByEntityId(model.EntityId);
        boolean isNew = UUIDUtil.isEmpty(model.RecordId);
        UUID thisId = UUIDUtil.Empty;
        try {
            com.xms.core.data.Entity entity = new com.xms.core.data.Entity(entityMetaData.getName());
            entity.setIdName(attributeMetaDatas.stream().filter(x -> AttributeExt.typeIsPrimaryKey(x)).findFirst().get().getName());
            JSONObject headData = JSONObject.parseObject(model.Data);
            Iterator iter = headData.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                String key = entry.getKey().toString().toLowerCase();
                Object value = entry.getValue();
                Attribute attr = attributeMetaDatas.stream().filter(n -> n.getName().equalsIgnoreCase(key)).findFirst().orElse(null);
                if (attr != null && value != null) {
                    entity.setValue(key, EntityWrapper.wrapAttributeValue(entity, _entityFinderService, attr, value));
                }
            }
            if (isNew) {
                thisId = UUIDUtil.Empty;
                if (StringUtil.notEmpty(model.RelationShipName) && UUIDUtil.notEmpty(model.ReferencedRecordId))//如果存在关联关系
                {
                    RelationShip relationShipMetas = _relationShipFinderService.getByName(model.RelationShipName);
                    if (null != relationShipMetas && relationShipMetas.getReferencingentityid().equals(model.EntityId)
                            && StringUtil.isEmpty(entity.getStringValue(relationShipMetas.getReferencingattributename()))) {
                        //设置当前记录关联字段的值
                        entity.setValue(relationShipMetas.getReferencingattributename(), new EntityReference(relationShipMetas.getReferencedentityname(), model.ReferencedRecordId));
                    }
                }
            } else {
                thisId = model.RecordId;
                entity.setIdValue(model.RecordId);
            }
            aggregateRoot.MainEntity = entity;
            aggregateRoot.ChildEntities = new ArrayList<>();
            //单据体
            if (StringUtil.notEmpty(model.Child)) {
                JSONArray childs = JSONArray.parseArray(StringUtil.urlDecode(model.Child));
                if (childs.size() > 0) {
                    //List<com.xms.core.data.Entity> childEntities = new ArrayList<>();
                    List<String> entityNames = new ArrayList<>();
                    Iterator childIter = childs.iterator();
                    while (childIter.hasNext()) {
                        JSONObject root = (JSONObject) childIter.next();
                        String name = root.getString("name"), child_relationshipname = root.getString("relationshipname"), refname = "";
                        Integer entitystatus = root.getInteger("entitystatus");
                        entitystatus = entitystatus == null ? 0 : entitystatus;
                        if (!entityNames.contains(name)) {
                            entityNames.add(name);
                        }

                        List<Attribute> childAttributes = _attributeFinderService.getByEntityName(name);
                        if (StringUtil.notEmpty(child_relationshipname)) {
                            RelationShip relationShipMetas = _relationShipFinderService.getByName(child_relationshipname);
                            if (null != relationShipMetas
                                    && relationShipMetas.getReferencedentityid().equals(model.EntityId)) {
                                refname = relationShipMetas.getReferencingattributename();
                            }
                        }
                        com.xms.core.data.Entity detail = new com.xms.core.data.Entity(name);
                        RefEntity refEntity = new RefEntity();
                        refEntity.Name = name;
                        refEntity.Relationshipname = child_relationshipname;
                        refEntity.Entityid = model.EntityId;
                        refEntity.Entitystatus = entitystatus;

                        JSONObject childDatas = root.getJSONObject("data");//.getJSONObject("data");
                        if (childDatas.size() > 0) {
                            Iterator childDataIter = childDatas.entrySet().iterator();
                            while (childDataIter.hasNext()) {
                                Map.Entry entry = (Map.Entry) childDataIter.next();
                                String key = entry.getKey().toString().toLowerCase();
                                Object value = entry.getValue();
                                Attribute attr = childAttributes.stream().filter(n -> n.getName().equalsIgnoreCase(key)).findFirst().orElse(null);
                                if (attr != null && value != null) {
                                    detail.setValue(key, EntityWrapper.wrapAttributeValue(detail, _entityFinderService, attr, value.toString()));
                                }
                            }
                            refEntity.Entity = detail;
                        }
                        //关联主记录ID
                        if (StringUtil.notEmpty(refname)) {
                            detail.setValue(refname, new EntityReference(entityMetaData.getName(), thisId));
                        }
                        aggregateRoot.ChildEntities.add(refEntity);
                    }
                }
            }

            //附件保存
            Collection<Part> parts = _request.getParts();
            if (parts != null && parts.size() > 0) {
                for (Part file : parts) {
                    if(file.getSubmittedFileName() == null) continue;
                    String inputName = file.getName();
                    Attribute attr = attributeMetaDatas.stream().filter(n -> n.getName().equalsIgnoreCase(inputName)).findFirst().orElse(null);
                    if (attr != null && attr.getDataformat().equalsIgnoreCase("fileupload")) {
                        Entity etAttachement = _attachmentCreaterService.create(model.EntityId, model.RecordId, file);
                        if (CollectionUtil.notEmpty(etAttachement)) {
                            entity.setValue(inputName, etAttachement.getStringValue("cdnpath"));
                        }
                    }
                }
            }

            if (isNew) {
                thisId = _aggCreater.create(aggregateRoot, thisId, model.FormId);
            } else {
                _aggUpdater.update(aggregateRoot, model.FormId);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return JError(ex.getMessage());
        }
        if (isNew) {
            return JCreateSuccess(KeyValuePair.build("id", thisId));
        }
        return JUpdateSuccess(KeyValuePair.build("id", thisId));
    }
}
